/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.manager.impl;

import com.xy.biz.base.dao.BomDao;
import com.xy.biz.base.dao.BomEquipmentDao;
import com.xy.biz.base.dao.BomGoodsDao;
import com.xy.biz.base.domain.bo.BomBO;
import com.xy.biz.base.domain.bo.BomEquipmentBO;
import com.xy.biz.base.domain.bo.BomGoodsBO;
import com.xy.biz.base.domain.converter.BomConverter;
import com.xy.biz.base.domain.converter.BomEquipmentConverter;
import com.xy.biz.base.domain.converter.BomGoodsConverter;
import com.xy.biz.base.domain.po.BomPO;
import com.xy.biz.base.domain.query.BomByIdQuery;
import com.xy.biz.base.domain.query.BomEquipmentQuery;
import com.xy.biz.base.domain.query.BomQuery;
import com.xy.biz.base.manager.BomManager;
import com.xy.lang.domain.Result;
import com.xy.lang.enums.ApplyStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zsp
 * @date 2021-12-28
 */
@Service
public class BomManagerImpl implements BomManager {

    @Autowired
    private BomDao bomDao;
    @Autowired
    private BomGoodsDao bomGoodsDao;
    @Autowired
    private BomEquipmentDao bomEquipmentDao;
//    @Autowired
//    private WorkFlowHandleClient workFlowHandleClient;

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public int saveBom(BomBO bomBO) {
        List<BomPO> bomPOList = bomDao.listBom(BomQuery.max()
                .goodsId(bomBO.getGoodsId())
                .status(ApplyStatusEnum.START.getCode())
                .build());
        if (!CollectionUtils.isEmpty(bomPOList) && !Objects.equals(true, bomBO.getCopyFlag())) {
            return -1;
        }
        BomPO bomPO = BomConverter.toPO(bomBO);
        int affectedRows = bomDao.saveBom(bomPO);
        if (affectedRows > 0) {
            if (!CollectionUtils.isEmpty(bomBO.getGoodsList())) {
                for (BomGoodsBO bomGoods : bomBO.getGoodsList()) {
                    bomGoods.setBomId(bomPO.getBomId());
                }
                affectedRows += bomGoodsDao.saveAllBomGoods(BomGoodsConverter.toPO(bomBO.getGoodsList()));
            }
            if (!CollectionUtils.isEmpty(bomBO.getEquipmentList())) {
                for (BomEquipmentBO bomEquipment : bomBO.getEquipmentList()) {
                    bomEquipment.setBomId(bomPO.getBomId());
                }
                affectedRows += bomEquipmentDao.saveAllBomEquipment(BomEquipmentConverter.toPO(bomBO.getEquipmentList()));
            }
        }
        return affectedRows;
    }

    @Override
    public int copyBom(BomBO bomBO) {
        List<BomGoodsBO> bomGoodsBOList =
                BomGoodsConverter.fromPO(bomGoodsDao.listBomGoodsByBomId(Collections.singletonList(bomBO.getBomId())));
        if (CollectionUtils.isEmpty(bomGoodsBOList)) {
            return -1;
        }
        bomGoodsBOList.forEach(e -> {
            e.setBomGoodsId(null);
            e.setUpdateTime(LocalDateTime.now());
        });
        bomBO.setStatus(ApplyStatusEnum.DRAFT.getCode());
        bomBO.setAuditStatus(0);
        bomBO.setBomId(null);
        bomBO.setAuditUserId(null);
        bomBO.setAuditTime(null);
        bomBO.setAuditUserName(null);
        bomBO.setAuditComment(null);
        bomBO.setCopyFlag(true);
        bomBO.setGoodsList(bomGoodsBOList);
        return saveBom(bomBO);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateBom(BomBO bomBO) {
        List<BomPO> bomPOList = bomDao.listBom(BomQuery.max()
                .goodsId(bomBO.getGoodsId())
                .status(ApplyStatusEnum.START.getCode())
                .build());
        if (!CollectionUtils.isEmpty(bomPOList)) {
            if (ApplyStatusEnum.START.getCode() == bomBO.getStatus()) {
                bomPOList = bomPOList.stream().filter(e -> !Objects.equals(e.getBomId(), bomBO.getBomId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(bomPOList)) {
                    return -1;
                }
            }
        }
        int row = bomDao.updateBom(BomConverter.toPO(bomBO));
        if (row > 0) {
            if (!CollectionUtils.isEmpty(bomBO.getGoodsList())) {
                row = bomGoodsDao.deleteBomGoodsByBomId(bomBO.getBomId());
                if (row < 1) {
                    throw new RuntimeException("Description Failed to delete the BOM goods list");
                }
                List<BomGoodsBO> bomGoodsList = bomBO.getGoodsList();
                for (BomGoodsBO bomGoods : bomGoodsList) {
                    bomGoods.setBomId(bomBO.getBomId());
                }
                row += bomGoodsDao.saveAllBomGoods(BomGoodsConverter.toPO(bomGoodsList));
            }
            if (!CollectionUtils.isEmpty(bomBO.getEquipmentList())) {
                row = bomEquipmentDao.deleteBomEquipmentByBomId(bomBO.getBomId());
                if (row < 1) {
                    throw new RuntimeException("Description Failed to delete the BOM equipment list");
                }
                List<BomEquipmentBO> equipmentList = bomBO.getEquipmentList();
                for (BomEquipmentBO bomEquipment : equipmentList) {
                    bomEquipment.setBomId(bomBO.getBomId());
                }
                row += bomEquipmentDao.saveAllBomEquipment(BomEquipmentConverter.toPO(bomBO.getEquipmentList()));
            }
        }
        return row;
    }

    /**
     * 审核
     * @param bomBO
     */
    @Override
    public int auditBom(BomBO bomBO) {
        return bomDao.auditBom(BomConverter.toPO(bomBO));
    }

    @Override
    public int deleteBom(Long bomId) {
        int row = bomDao.deleteBom(bomId);
        if (row > 0) {
            bomGoodsDao.deleteBomGoodsByBomId(bomId);
        }
        return row;
    }

    @Override
    public BomBO getBom(BomByIdQuery query) {
        BomBO bomBO = BomConverter.fromPO(bomDao.getBom(query.getBomId()));
        build(query.getWithGoods(), query.getWithEquipment(), query.getWithFlowHandleInfo(), Collections.singletonList(bomBO));
        return bomBO;
    }

    @Override
    public List<BomBO> listBomById(Collection<Long> collection) {
        return BomConverter.fromPO(bomDao.listBomById(collection));
    }

    @Override
    public List<BomBO> listBom(BomQuery query) {
        List<BomBO> bomBOList = BomConverter.fromPO(bomDao.listBom(query));
        build(query.getWithGoods(), query.getWithEquipment(), false, bomBOList);
        return bomBOList;
    }

    private void build(boolean withGoods, boolean withEquipment, boolean withFlowHandleInfo, List<BomBO> bomBOList) {
        if (CollectionUtils.isEmpty(bomBOList)) {
            return;
        }
        Map<Long, List<BomGoodsBO>> bomGoodsBOGroup = new HashMap<>();
        Set<Long> bomIdSet = bomBOList.stream()
                .map(BomBO::getBomId)
                .collect(Collectors.toSet());
        if (withGoods) {
            List<BomGoodsBO> bomGoodsBOList
                    = BomGoodsConverter.fromPO(bomGoodsDao.listBomGoodsByBomId(bomIdSet));
            bomGoodsBOGroup =
                    bomGoodsBOList.stream().collect(Collectors.groupingBy(BomGoodsBO::getBomId));
        }
        Map<Long, List<BomEquipmentBO>> bomEquipmentGroup = new HashMap<>();
        if (withEquipment) {
            List<BomEquipmentBO> bomEquipmentBOList = BomEquipmentConverter.fromPO(bomEquipmentDao.listBomEquipment(BomEquipmentQuery.max()
                    .bomIdList(new ArrayList<>(bomIdSet))
                    .build()));
            bomEquipmentGroup =
                    bomEquipmentBOList.stream().collect(Collectors.groupingBy(BomEquipmentBO::getBomId));
        }

        for (BomBO bomBO : bomBOList) {
            if (bomGoodsBOGroup.containsKey(bomBO.getBomId())) {
                List<BomGoodsBO> bomGoodsBOS = bomGoodsBOGroup.get(bomBO.getBomId());
                bomBO.setGoodsList(bomGoodsBOS);
            }
            if (bomEquipmentGroup.containsKey(bomBO.getBomId())) {
                bomBO.setEquipmentList(bomEquipmentGroup.get(bomBO.getBomId()));
            }
        }
    }

    @Override
    public int countBom(BomQuery query) {
        return bomDao.countBom(query);
    }

}
